#ifndef SPECTRUM_DYNAMIC_H
#define SPECTRUM_DYNAMIC_H

#include <string>
#include <math.h>
#include <vector>

namespace gemren
{
	struct spectrum_dynamic
	{
		static const float infinity;
		spectrum_dynamic():len(0), vals(NULL) {}
		spectrum_dynamic(const spectrum_dynamic& s): len(s.len)
		{
			vals = new float[len+1];
			std::copy(s.vals, s.vals+len+1, vals);
		}
		spectrum_dynamic(const std::string& value, float min, float max)
		{
			std::vector<float> vvals;
			std::stringstream ss(value);
			
			while(!ss.eof())
			{
				float val;
				ss>>val;
				if(ss.fail())
					break;
				vvals.push_back(embree::clamp(val, min, max));
			}
			if(vvals.size() == 0)
			{
				len = 0;
				vals = new float[1];
				vals[0] = 0.0f;
			}
			else
			{
				vals = new float[vvals.size()];
				std::copy(vvals.begin(), vvals.end(), vals);
				len = int(vvals.size() - 1);
			}
		}
		~spectrum_dynamic(){ delete[] vals; }
		bool is_const()const{ return len==0; }
		spectrum_dynamic& operator=(const spectrum_dynamic& s)
		{
			delete []vals;
			len = s.len;
			vals = new float[len+1];
			std::copy(s.vals, s.vals+len+1, vals);
			return *this;
		}
		template<typename Iter>
		spectrum_dynamic(const Iter& begin, const Iter& end)
			:len(int(end-begin-1))
		{
			vals = new float[len+1];
			std::copy(begin, end, vals);
		
		}
		spectrum_dynamic(float val): len(0), vals(new float[1]) { vals[0] = val; }
		float operator[](float wavelength) const
		{
			return at(wavelength);
		}
		inline float at(float wavelength) const
		{
			wavelength *= len;
			int left = int(wavelength), right = int(ceil(wavelength));
			float weight = fmod(wavelength, 1.0f);
			return (1.0f-weight)*vals[left] + weight*vals[right];
		}
		friend class color_converter;

		std::string to_string()
		{
			std::stringstream ss;
			for(int i = 0; i <= len; ++i)
				ss<<vals[i]<<" ";
			return ss.str();
		}
		size_t interval_count()const { return len; }
		int getl() const { return len; }
		float getv(int i) const { return vals[i]; } 
		
		
		template<typename S>
		void limit(const S& nmax)
		{
			if(len == 0)
				vals[0] = min(vals[0], nmax.integral());
			else
			for(int i = 0; i <= len; ++i)
			{
				float pos = float(i)/len;
				vals[i] = min(vals[i], nmax[pos]);
			}
		}
	protected:
		inline float min(const float a, const float b){ return a<b?a:b; }
		int len; //number of intervals = # of vals - 1
		float* vals;
	};
}

#endif